package com.clp.util.hutool.core.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class ModifierUtil {

    public enum ModifierType {
        PUBLIC(Modifier.PUBLIC),
        PRIVATE(Modifier.PRIVATE),
        PROTECTED(Modifier.PROTECTED),
        STATIC(Modifier.STATIC),
        FINAL(Modifier.FINAL),
        SYNCHRONIZED(Modifier.SYNCHRONIZED),
        VOLATILE(Modifier.VOLATILE),
        TRANSIENT(Modifier.TRANSIENT),
        NATIVE(Modifier.NATIVE),
        ABSTRACT(Modifier.ABSTRACT),
        STRICT(Modifier.STRICT);

        private final int value;

        ModifierType(int modifier) {
            this.value = modifier;
        }

        public int getValue() {
            return this.value;
        }
    }

    public static boolean isPublic(Field field) {
        return hasModifier(field, ModifierType.PUBLIC);
    }

    public static boolean hasModifier(Field field, ModifierType... modifierTypes) {
        if (null == field || ArrayUtil.isEmpty(modifierTypes)) {
            return false;
        }
        return 0 != (field.getModifiers() & modifiersToInt(modifierTypes));
    }

    /**
     * 是否同时存在一个或多个修饰符（可能有多个修饰符，如果有指定的修饰符则返回true）
     *
     * @param clazz 类
     * @param modifierTypes 修饰符枚举
     * @return 是否有指定修饰符，如果有返回true，否则false，如果提供参数为null返回false
     */
    public static boolean hasModifier(Class<?> clazz, ModifierType... modifierTypes) {
        if (null == clazz || ArrayUtil.isEmpty(modifierTypes)) {
            return false;
        }
        return 0 != (clazz.getModifiers() & modifiersToInt(modifierTypes));
    }

    private static int modifiersToInt(ModifierType... modifierTypes) {
        int modifier = modifierTypes[0].getValue();
        for (int i = 0; i < modifierTypes.length; i++) {
            modifier |= modifierTypes[i].getValue();
        }
        return modifier;
    }

    public static boolean isStatic(Field field) {
        return hasModifier(field, ModifierType.STATIC);
    }

    /**
     * 是否同时存在一个或多个修饰符（可能有多个修饰符，如果有指定的修饰符则返回true）
     *
     * @param method 方法
     * @param modifierTypes 修饰符枚举
     * @return 是否有指定修饰符，如果有返回true，否则false，如果提供参数为null返回false
     */
    public static boolean hasModifier(Method method, ModifierType... modifierTypes) {
        if (null == method || ArrayUtil.isEmpty(modifierTypes)) {
            return false;
        }
        return 0 != (method.getModifiers() & modifiersToInt(modifierTypes));
    }

    public static boolean isStatic(Method method) {
        return hasModifier(method, ModifierType.STATIC);
    }
}
